package com.atm.publish;


import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

@Controller
@RequestMapping("/")
public class PublishController {

    private static Logger logger = LoggerFactory.getLogger(PublishController.class);

    private final String prefix = "publish";

    // 显示发布页面
    @GetMapping("/info")
    public String info(HttpServletRequest request, Model model) {
        String projectServerNo = request.getParameter("projectServerNo");
        if (StringUtils.isNotEmpty(projectServerNo)) {
            ProjectServerVo projectServerVo = PublishConst.projectServerVoMap.get(projectServerNo);
            model.addAttribute("projectServerVo", projectServerVo);
        }
        return prefix + "/info";
    }

    @GetMapping("/")
    public String list(Model model) {
        model.addAttribute("projectServerVoList", PublishConst.projectServerVoList);
        return prefix + "/list";
    }

    @PostMapping("/upload")
    @ResponseBody
    public String uploadFile(@RequestParam("projectServerNo") String projectServerNo
            , @RequestParam("file") MultipartFile file) {
        if (StringUtils.isEmpty(projectServerNo)) {
            return "项目编号不正确为空";
        }
        ProjectServerVo projectServerVo = PublishConst.projectServerVoMap.get(projectServerNo);
        if (projectServerVo == null) {
            return "项目编号不正确为空";
        }
        try {
            // 将上传的文件保存到本地临时文件
            File tempFile = File.createTempFile("upload-", file.getOriginalFilename());
            try (FileOutputStream fos = new FileOutputStream(tempFile)) {
                fos.write(file.getBytes());
            }
            // 创建 JSch 会话并连接到服务器
            JSch jsch = new JSch();
            Session session = jsch.getSession(projectServerVo.getUsername(), projectServerVo.getIp(), 22);
            session.setPassword(projectServerVo.getPassword());
            session.setTimeout(30000);

            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();
            // 打开 SFTP 通道
            Channel channel = session.openChannel("sftp");
            channel.connect();
            ChannelSftp sftpChannel = (ChannelSftp) channel;
            // 上传文件到服务器
            sftpChannel.put(tempFile.getAbsolutePath(),
                    projectServerVo.getUploadPath() + "/" + file.getOriginalFilename());
            // 关闭连接和删除临时文件
            sftpChannel.disconnect();
            channel.disconnect();
            session.disconnect();
            tempFile.delete();
            return "文件上传成功";
        } catch (JSchException | IOException e) {
            e.printStackTrace();
            return "上传失败: " + e.getMessage();
        } catch (SftpException e) {
            throw new RuntimeException(e);
        }
    }

    @PostMapping("/deploy")
    @ResponseBody
    public String deployProject(@RequestParam("projectServerNo") String projectServerNo) {
        if (StringUtils.isEmpty(projectServerNo)) {
            return "项目编号不正确为空";
        }
        ProjectServerVo projectServerVo = PublishConst.projectServerVoMap.get(projectServerNo);
        if (projectServerVo == null) {
            return "项目编号不正确为空";
        }
        StringBuilder output = new StringBuilder();
        try {
            String deployScript = projectServerVo.getDeployPath();
            // 获取路径和文件名
            String dirPath = deployScript.substring(0, deployScript.lastIndexOf("/"));
            String fileName = deployScript.substring(deployScript.lastIndexOf("/") + 1);

            // 执行命令
            String command = "cd " + dirPath + " && sh " + fileName;

            JSch jsch = new JSch();
            Session session = jsch.getSession(projectServerVo.getUsername(), projectServerVo.getIp(), 22);
            session.setPassword(projectServerVo.getPassword());
            session.setTimeout(10000);

            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();
            Channel channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand(command);
            channel.setInputStream(null);
            ((ChannelExec) channel).setErrStream(System.err);
            channel.connect();
            InputStream in = channel.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
            }
            channel.disconnect();
            session.disconnect();
            return "项目发布成功，输出如下：\n" + output.toString();
        } catch (JSchException | IOException e) {
            e.printStackTrace();
            return "项目发布失败: " + e.getMessage();
        }
    }

    @PostMapping("/viewLogs")
    @ResponseBody
    public String viewLogs(@RequestParam("projectServerNo") String projectServerNo) {

        if (StringUtils.isEmpty(projectServerNo)) {
            return "项目编号不正确为空";
        }
        ProjectServerVo projectServerVo = PublishConst.projectServerVoMap.get(projectServerNo);
        if (projectServerVo == null) {
            return "项目编号不正确为空";
        }
        StringBuilder logContent = new StringBuilder();
        try {
            JSch jsch = new JSch();
            Session session = jsch.getSession(projectServerVo.getUsername(), projectServerVo.getIp(), 22);
            session.setPassword(projectServerVo.getPassword());
            session.setTimeout(10000);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();
            Channel channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand("tail -n 50 " + projectServerVo.getLogPath()); // 取最后 50 行日志
            channel.setInputStream(null);
            ((ChannelExec) channel).setErrStream(System.err);
            channel.connect();
            InputStream in = channel.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String line;
            while ((line = reader.readLine()) != null) {
                logContent.append(line).append("\n");
            }
            channel.disconnect();
            session.disconnect();
        } catch (JSchException | IOException e) {
            e.printStackTrace();
            logContent.append("查看日志失败: ").append(e.getMessage());
        }
        return logContent.toString();
    }

}
